﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace Common
{
  /// <summary>
  /// 对象复制
  /// </summary>
  /// <typeparam name="TIn"></typeparam>
  /// <typeparam name="TOut"></typeparam>
  public static class ObjCopy<TIn, TOut>
  {
    private static readonly Func<TIn, TOut> cache = GetFunc();
    private static Func<TIn, TOut> GetFunc()
    {
      ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
      List<MemberBinding> memberBindingList = new List<MemberBinding>();

      foreach (var item in typeof(TIn).GetProperties())
      {
        if (!item.CanWrite)
          continue;

        MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
        MemberBinding memberBinding = Expression.Bind(item, property);
        memberBindingList.Add(memberBinding);
      }

      MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
      Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[] { parameterExpression });

      return lambda.Compile();
    }

    public static TOut Trans(TIn tIn)
    {
      return cache(tIn);
    }
  }
}
